package com.material.fish;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.ImageView;
import android.widget.RelativeLayout;

/**
 * @author linzhi <a href="mailto:zhilinchn@126.com">Contact me.</a>
 * @version 1.0
 * @since 2021/10/23 5:50 下午
 */
public class FishRelativeLayout extends RelativeLayout {

  private Paint mPaint;
  private ImageView ivFish;
  private FishDrawable fishDrawable;
  private float touchX;
  private float touchY;

  private int alpha;

  public float getRipple() {
    return ripple;
  }

  public void setRipple(float ripple) {
    //alpha 100 - 0
    alpha = (int) (100 * (1 - ripple));
    this.ripple = ripple;
  }

  private float ripple;

  public FishRelativeLayout(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
  }

  public FishRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    this(context, attrs, defStyleAttr, 0);
  }

  public FishRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr,
      int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
    init(context);
  }

  public FishRelativeLayout(Context context) {
    this(context, null);
  }

  private void init(Context context) {
    setWillNotDraw(false);
    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setDither(true);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeWidth(8);

    ivFish = new ImageView(context);
    LayoutParams layoutParams =
        new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    ivFish.setLayoutParams(layoutParams);
    fishDrawable = new FishDrawable();
    ivFish.setImageDrawable(fishDrawable);
    addView(ivFish);
  }

  @Override protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    mPaint.setAlpha(alpha);
    canvas.drawCircle(touchX, touchY, ripple * 150, mPaint);
    invalidate();
  }

  @Override public boolean onTouchEvent(MotionEvent event) {
    touchX = event.getX();
    touchY = event.getY();

    mPaint.setAlpha(100);
    ObjectAnimator anim = ObjectAnimator.ofFloat(this, "ripple", 0, 1f)
        .setDuration(1000);
    anim.start();
    makeTrail();

    return super.onTouchEvent(event);
  }

  private void makeTrail() {
    //鱼相对ImageView的重心坐标
    PointF fishRelative = fishDrawable.getMiddlePoint();
    PointF fishMiddle = new PointF(ivFish.getX() + fishRelative.x, ivFish.getY() + fishRelative.y);
    // 鱼头坐标 控制点1
    PointF fishHead = new PointF(ivFish.getX() + fishDrawable.getFishHeadPoint().x,
        ivFish.getY() + fishDrawable.getFishHeadPoint().y);
    PointF touch = new PointF(touchX, touchY);
    float angle = includeAngel(fishMiddle, fishHead, touch) / 2;
    float delta = includeAngel(fishMiddle, new PointF(fishMiddle.x, fishMiddle.y), fishHead);

    // 控制点2
    PointF controlPoint =
        fishDrawable.calculatePoint(fishMiddle, FishDrawable.HEAD_RADIUS * 1.6f, angle + delta);

    Path path = new Path();
    path.moveTo(fishMiddle.x - fishRelative.x, fishMiddle.y - fishRelative.y);
    path.cubicTo(fishHead.x - fishRelative.x, fishHead.y - fishRelative.y,
        controlPoint.x - fishRelative.x, controlPoint.y - fishRelative.y, touchX - fishRelative.x,
        touchY - fishRelative.y);

    final ObjectAnimator animator = ObjectAnimator.ofFloat(ivFish, "x", "y", path);
    animator.setDuration(2000);


    animator.addListener(new AnimatorListenerAdapter() {
      @Override public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        fishDrawable.setFrequency(1f);
      }




      @Override public void onAnimationStart(Animator animation) {
        super.onAnimationStart(animation);
        fishDrawable.setFrequency(2f);
      }
    });
    animator.start();

    final PathMeasure pathMeasure = new PathMeasure(path, false);
    final float[] tan = new float[2];
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
      @Override public void onAnimationUpdate(ValueAnimator animation) {
        //整个周期的百分比
        float percent = animation.getAnimatedFraction();
        pathMeasure.getPosTan(pathMeasure.getLength() * percent, null, tan);
        float angle = (float) Math.toDegrees(Math.atan2(-tan[1],tan[0]));
        fishDrawable.setFishMainAngle(angle);
      }
    });

  }

  public float includeAngel(PointF O, PointF A, PointF B) {
    // cosAOB
    // OA*OB=(Ax-Ox)(Bx-Ox)+(Ay-Oy)*(By-Oy)
    float AOB = (A.x - O.x) * (B.x - O.x) + (A.y - O.y) * (B.y - O.y);
    float OALength = (float) Math.sqrt((A.x - O.x) * (A.x - O.x) + (A.y - O.y) * (A.y - O.y));

    // OB 的长度
    float OBLength = (float) Math.sqrt((B.x - O.x) * (B.x - O.x) + (B.y - O.y) * (B.y - O.y));

    float cosAOB = AOB / (OALength * OBLength);

    // 反余弦
    float angleAOB = (float) Math.toDegrees(Math.acos(cosAOB));

    // AB连线与X的夹角的tan值 - OB与x轴的夹角的tan值
    float direction = (A.y - B.y) / (A.x - B.x) - (O.y - B.y) / (O.x - B.x);

    if (direction == 0) {
      if (AOB >= 0) {
        return 0;
      } else {
        return 180;
      }
    } else {
      if (direction > 0) {
        return -angleAOB;
      } else {
        return angleAOB;
      }
    }
  }
}
